package com.hoshiicloud.auth.controller;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.hoshiicloud.BackSysUsersVO;
import com.hoshiicloud.auth.feign.VeriCenterFeignService;
import com.hoshiicloud.auth.service.CompanyUserService;
import com.hoshiicloud.auth.service.UserService;
import com.hoshiicloud.auth.vo.LoginVO;
import com.hoshiicloud.auth.vo.TokenUsersVO;
import com.hoshiicloud.common.constant.TokenUserFieldEnum;
import com.hoshiicloud.common.exception.ServiceException;
import com.hoshiicloud.common.rpc.Response;
import com.hoshiicloud.common.utils.DigestUtils;
import com.hoshiicloud.common.utils.SMSCodeUtil;
import com.hoshiicloud.common.utils.token.JWTUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Api(tags = "登录授权接口")
@RestController
@Slf4j
//TODO 租户登录获取信息接口
//TODO 租户密码登录接口
//TODO 租户手机验证码登录
//TODO 租户员工登录
//TODO 租户相关系统SSO登录
public class WebController {

    @Autowired
    private VeriCenterFeignService veriCenterFeignService;
    @Autowired
    private UserService userService;
    @Autowired
    private CompanyUserService companyUserService;
    @Resource
    private RedisTemplate redisTemplate;

    @Autowired
    public void setService(UserService userService) {
        this.userService = userService;
    }

    @ApiOperation(value = "发送手机验证码")
    @PostMapping("/sendPhoneCode")
    public Response sendPhoneCode(String phone) {
        String regex = "^(13[0-9]|14[5|6|7|8|9]|15[0|1|2|3|5|6|7|8|9]|16[5|6]|17[0-8]|18[0-9]|19[1|8|9])\\d{8}$";
        if (phone.matches(regex)) {
            String code = SMSCodeUtil.getRandom(6);
            Long expSecond = 180L;
            return veriCenterFeignService.sendCode(phone, code, expSecond);
        } else {
            return Response.failed("手机号不合法");
        }

    }

    /**
     * @param companyId
     * @param privateDomain
     * @param userName
     * @param password
     * @return
     * @see #checkUserNamePassWord(String, String) 检查用户名密码
     */
    @ApiOperation(value = "租户会员密码登录")
    @PostMapping("/memberLogin")
    public Response memberLogin(@RequestHeader("privateDomain") String privateDomain,
            @RequestParam("userName") String userName, @RequestParam("password") String password) {
        this.checkUserNamePassWord(userName, password);
        return companyUserService.memberPasswordLogin(privateDomain, userName, password);
    }

    @ApiOperation(value = "租户用户管理后台登录")
    @PostMapping("/companyUserLogin")
    public Response<LoginVO> companyUserLogin(String userName, String password,
            @RequestHeader("privateDomain") String subDomain) {
        this.checkUserNamePassWord(userName, password);
        return companyUserService.companyUserLogin(subDomain, userName, password);
    }

    @ApiOperation(value = "租户用户管理后台切换账号")
    @PostMapping("/companyUserAccessToken")
    public Response<LoginVO> companyUserAccessToken(@RequestParam("token") String token) {
        return companyUserService.companyUserAccessToken(token);
    }

    @PostMapping("/memberAccessToken")
    public Response<LoginVO> memberAccessToken(String token) {
        return companyUserService.getMemberAccessToken(token);
    }

    @ApiOperation(value = "平台登录")
    @PostMapping("/platformLogin")
    public Response platformLogin(@RequestParam("platformId") Long platformId, @RequestParam("token") String token) {
        return companyUserService.getPlatformUserAccessToken(platformId, token);
    }

    @ApiOperation(value = "店铺登录")
    @PostMapping("/storeLogin")
    public Response storeLogin(@RequestParam("storeId") Long storeId, @RequestParam("token") String token) {
        return companyUserService.getStoreUserAccessToken(storeId, token);
    }

    @ApiOperation(value = "saas管理登录")
    @PostMapping("/saaaLogin")
    public Response saasLogin() {
        return null;
    }

    @ApiOperation(value = "注销")
    @PostMapping("/logout")
    public Response logout(String token) {
        try{
            DecodedJWT jwt= JWTUtil.getDecodedJWT(token);
            String loginKey=jwt.getClaim(TokenUserFieldEnum.LOGIN_KEY.getName()).asString();
            redisTemplate.delete(loginKey);
            return Response.success("注销成功");
        }catch (Exception e){
            return Response.success("注销成功");
        }
        /*
        Subject subject = SecurityUtils.getSubject();
        if(subject.isAuthenticated()){
            String token=subject.getPrincipal().toString();
            DecodedJWT jwt= JWTUtil.getDecodedJWT(token);
            if(jwt==null){
                return Response.failed("注销失败,登录信息有误");
            }
            String userName=jwt.getClaim("userName").asString();
            String platformId=jwt.getClaim("platformId").asString();
            String md5= DigestUtils.md5(platformId+userName);
            redisTemplate.delete(md5);
            return Response.success("注销成功");
        }
        return Response.failed("注销失败,尚未登录");
        */

    }


    @ApiOperation(value = "注销")
    @PostMapping("/logout2")
    public Response logout2(@RequestBody String key) {
        String md5 = DigestUtils.md5(key);
        redisTemplate.delete(md5);
        return Response.success("注销成功");
    }

    @ApiOperation(value = "登录")
    @PostMapping("/login")
    public Response login(@RequestParam("userName") String userName,
            @RequestParam("password") String password, @RequestParam("userType") String userType,
            @RequestParam("platformId") String platformId) {
        this.checkUserNamePassWord(userName, password);

        BackSysUsersVO userBean = null;
        try {
            userBean = userService.getUser(userName, userType);
        } catch (Exception e) {
            return Response.failed(e.getMessage());
        }
        if (null == userBean) {
            return Response.failed("获取用户信息失败");
        }
        /*if(null == userBean.getLocked() || 1 ==  userBean.getLocked()){
            return Response.failed("该用户已被锁定");
        }*/
        if (userBean.getPassword().equals(password)) {
            String realName = userBean.getRealName();
            String token = JWTUtil.sign(userName, realName, userType, platformId, null, password);
            //将token保存到redis
            String loginKey = DigestUtils.md5(platformId + userName);
            log.info("loginKey:" + loginKey);
            userBean.setPassword(null);
            userBean.setToken(token);
            userBean.setUserType(userType);
            userBean.setPlatformId(platformId);
            //登录有效期由redis控制,token本身无限期
            redisTemplate.opsForValue().set(loginKey, userBean, 1, TimeUnit.DAYS);
            return new Response(200, "Login success", token);
        } else {
            return Response.failed("用户名或密码错误");
        }
    }


    @ApiOperation(value = "店铺登录")
    @PostMapping("/mall-shop-login")
    public Response mallShopLogin(@RequestParam("userName") String userName,
            @RequestParam("password") String password,
            @RequestParam("userType") String userType,
            @RequestParam("storeId") Long storeId) {
        this.checkUserNamePassWord(userName, password);
        TokenUsersVO userBean = userService.getStoreUser(userName, storeId);
        this.checkUser(userBean);
        //将token保存到redis
        String loginKey = DigestUtils.md5(userType + userName);
        return trueUserSetToken(userName, password, userType, userBean, loginKey);
    }


    @ApiOperation(value = "租户登录")
    @PostMapping("/lessee-login")
    public Response lesseeLogin(@RequestParam("userName") String userName,
            @RequestParam("password") String password,
            @RequestParam("userType") String userType,
            @RequestParam("privateDomain") String privateDomain) {
        this.checkUserNamePassWord(userName, password);
        TokenUsersVO userBean = userService.getCompanyUser(userName, privateDomain);
        this.checkUser(userBean);
        String loginKey = DigestUtils.md5(userType + userName + privateDomain);
        return trueUserSetToken(userName, password, userType, userBean, loginKey);
    }

    private Response trueUserSetToken(@RequestParam("userName") String userName, @RequestParam("password") String password,
            @RequestParam("userType") String userType, TokenUsersVO userBean, String loginKey) {
        if (userBean.getPassword().equals(password)) {
            String realName = userBean.getRealName();
            String token = JWTUtil.signAll(userName, realName, userType, userBean.getPlatId(),
                    userBean.getStoreId(), userBean.getCompanyId(), userBean.getUserId()
                    , password);
            log.info("loginKey:" + loginKey);
            userBean.setPassword(null);
            userBean.setToken(token);
            userBean.setUserType(userType);
            //登录有效期由redis控制,token本身无限期
            redisTemplate.opsForValue().set(loginKey, userBean, 1, TimeUnit.DAYS);
            Map<String, Object> map = new HashMap<>();
            map.put("token", token);
            return Response.data(map);
        } else {
            return Response.failed("用户名或密码错误");
        }
    }

    private void checkUser(TokenUsersVO userBean) {
        if (null == userBean) {
            throw new ServiceException("获取用户信息失败");
        }
        /*if(null == userBean.getLocked() || 1 ==  userBean.getLocked()){
            throw new ServiceException("该用户已被锁定");
        }*/
    }

    private void checkUserNamePassWord(@RequestParam("userName") String userName, @RequestParam("password") String password) {
        if (StringUtils.isBlank(userName) || StringUtils.isBlank(password)) {
            throw new ServiceException("请输入用户名或密码");
        }
    }
}
